package com.snow.jvm;

import java.util.Date;

/**
 * @类名称：JVM第一节
 * @类描述：
 * @author: bingHeng
 * @Date 2019.04.14
 * @Version: 1.0
*/
public class MyClassLoader {

    /**
     * 类装载器ClassLoader：负责加载class文件，class文件在文件开头有特定的文件标示，并且ClassLoader只负责class文件的加载，至于它是否可以运行，则由Execution Engine决定。
     *
     * ClassLoader: 虚拟机自带的加载器、用户自定义的加载器
     *
     * 虚拟机自带的加载器：启动类加载器（Bootstrap）、扩展类加载器（Extension）、应用程序类加载器（App）
     *
     * 启动类加载器（Bootstrap）：c++编写
     *
     * 扩展类加载器（Extension）：Java编写
     *
     * 应用程序类加载器（App）：Java编写，也叫系统类加载器，加载当前应用的classpath的所有类
     *
     *
     * 用户自定义的加载器： Java.lang.ClassLoader的子类，用户可以定制类的加载方式
     *
     *
     *  Java刚刚开始运行的时候会通过Bootstrap类加载器将Java自带的内容罗列出来，
     */
    public static void main(String[] args) throws ClassNotFoundException {
        Object object = new Object();
        System.out.println("获取Object对象的类加载器：" + object.getClass().getClassLoader()); // 获取该对象的类加载器

        Date date = new Date();
        System.out.println("获取Date对象的类加载器：" + date.getClass().getClassLoader());

        MyClassLoader myClassLoader = new MyClassLoader();
        System.out.println("获取自建类MyClassLoader的类加载器：" + myClassLoader.getClass().getClassLoader());

        Class clazz = Class.forName("com.snow.jvm.hello.MyHello");
        System.out.println("-----------" + clazz.getClassLoader());

        System.out.println("==============================我是华丽分割线==============================");

        System.out.println("获取自建类MyClassLoader父类的类加载器：（MyClassLoader的爸爸）" + myClassLoader.getClass().getClassLoader().getParent());

        System.out.println("获取自建类MyClassLoader父类的父类类加载器：（MyClassLoader的爷爷）" + myClassLoader.getClass().getClassLoader().getParent().getParent());

        /**
         * 对于根加载器Bootstrap，java自带的对象获取到的加载器类型为null（obj示例），对于我们自建的类，获取到的类加载器为：AppClassLoader
         *
         * 将MyHello.class文件打成.jar文件，放入到：D:\Program Files\java\jdk1.8.0_112\jre\lib\ext\MyHello.jar 文件夹中,并删除项目中的MyHello.java文件，
         * 此时控制台打印的是：sun.misc.Launcher$ExtClassLoader@2f2c9b19，说明这次采用的是ExtClassLoader拓展类加载器
         *
         *  从运行程序可以看出：
         *      MyClassLoader类的加载器为：AppClassLoader
         *      MyClassLoader父类的加载器为：ExtClassLoader
         *      MyClassLoader父类的父类加载器为：null(也就是Java的根加载器：Bootstrap)
         *
         *      所以我们可以说：应用类加载器继承了扩展类加载器，拓展类加载器继承了启动类加载器，所以Java的类装载器共计三种。
         *
         * ClassLoader是一个抽象类，言下之意我们自定义的东西都可以继承该类，来重写我们需要的方法和功能。也就是在开头说的：用户自定义的加载器
         */

        /**
         * 类装载器2：
         *  sun.misc.Launcher：它是一个Java虚拟机的入口应用，某个特定的类加载器在接到加载类的请求时，首先将加载任务委托给父类加载器，依次递归，如果父类加载器可以完成加载任务，就会成功返回。
         *  只有父类的加载器无法完成此加载任务时，才自己去加载。这就是Java的双亲委派机制。
         */

        /**
         * PC寄存器：每个线程都有一个程序计数器，是线程私有的，就是一个指针，指向方法区中的方法字节码（用来储存指向下一条指令的地址，也即将要执行的指令代码），由执行引擎读取下一条指令，
         * 是一个非常小的内存空间，几乎可以忽略不计。
         */
    }
}
